package org.papervision3d.core
{
    //The Number3D class represents a value in a three-dimensional coordinate system.
    //Properties x, y and z represent the horizontal, vertical and z the depth axes respectively.
    public class Number3D
    {
        //The horizontal coordinate value.
        public var x:Number;
    
        //The vertical coordinate value.
        public var y:Number;
    
        //The depth coordinate value.
        public var z:Number;
    
    
        //Creates a new Number3D object whose three-dimensional values are specified by the x, y and z parameters. If you call this constructor function without parameters, a Number3D with x, y and z properties set to zero is created.
        //@param x The horizontal coordinate value. The default value is zero.
        //@param y The vertical coordinate value. The default value is zero.
        //@param z The depth coordinate value. The default value is zero.
        public function Number3D(x:Number = 0, y:Number = 0, z:Number = 0)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    
        //Returns a new Number3D object that is a clone of the original instance with the same three-dimensional values.
        //@return   A new Number3D instance with the same three-dimensional values as the original Number3D instance.
        public function clone():Number3D
        {
            return new Number3D(this.x, this.y, this.z);
        }
    
        //Modulo
        public function get modulo():Number
        {
            return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
        }
    
        //Add
        public static function add(v:Number3D, w:Number3D):Number3D
        {
            return new Number3D
            (
                v.x + w.x,
                v.y + w.y,
                v.z + w.z
           );
        }
    
        //Substract.
        public static function sub(v:Number3D, w:Number3D):Number3D
        {
            return new Number3D
            (
                v.x - w.x,
                v.y - w.y,
                v.z - w.z
           );
        }
    
        //Dot product.
        public static function dot(v:Number3D, w:Number3D):Number
        {
            return (v.x * w.x + v.y * w.y + w.z * v.z);
        }
    
        //Cross product.
        public static function cross(v:Number3D, w:Number3D):Number3D
        {
            return new Number3D
            (
                (w.y * v.z) - (w.z * v.y),
                (w.z * v.x) - (w.x * v.z),
                (w.x * v.y) - (w.y * v.x)
           );
        }
    
        //Normalize.
        public function normalize():void
        {
            var mod:Number = this.modulo;
    
            if (mod != 0 && mod != 1)
            {
                this.x /= mod;
                this.y /= mod;
                this.z /= mod;
            }
        }
    
        //Returns a Number3D object with x, y and z properties set to zero.
        //@return A Number3D object.
        static public function get ZERO():Number3D
        {
            return new Number3D(0, 0, 0);
        }
        
        public function matrixTransform( m : Matrix3D ) : void {
            var vx:Number = x;
            var vy:Number = y;
            var vz:Number = z;

            var sx:Number = vx * m.n11 + vy * m.n12 + vz * m.n13 + m.n14;
            var sy:Number = vx * m.n21 + vy * m.n22 + vz * m.n23 + m.n24;
            var sz:Number = vx * m.n31 + vy * m.n32 + vz * m.n33 + m.n34;

			x = sx;
			y = sy;
			z = sz;
		}
    
        //Returns a string value representing the three-dimensional values in the specified Number3D object.
        //@return   A string.
        public function toString(): String
        {
            return 'x:' + x + ' y:' + y + ' z:' + z;
        }
    }
}